#include "stdafx.h"
#include "SourceView.h"
#include "SourceViewPage.h"

LUA_DEBUG_BEGIN


/*-----------------------------------------------------------------*/
BEGIN_EVENT_TABLE(SourceView, wxAuiNotebook)
EVT_DEBUG_END_DEBUG          (wxID_ANY, SourceView::OnEndDebug)
EVT_DEBUG_CHANGED_STATE      (wxID_ANY, SourceView::OnChangedState)
EVT_DEBUG_UPDATE_SOURCE      (wxID_ANY, SourceView::OnUpdateSource)
EVT_DEBUG_ADDED_SOURCE       (wxID_ANY, SourceView::OnAddedSource)
EVT_DEBUG_FOCUS_ERRORLINE    (wxID_ANY, SourceView::OnFocusErrorLine)
EVT_DEBUG_FOCUS_BACKTRACELINE(wxID_ANY, SourceView::OnFocusBacktraceLine)
END_EVENT_TABLE()

//SourceView::SourceView(wxWindow *parent)
//: wxAuiNotebook(parent, ID_SOURCEVIEW, wxDefaultPosition, wxDefaultSize,
//                wxAUI_NB_TOP | wxAUI_NB_TAB_MOVE | wxAUI_NB_SCROLL_BUTTONS)
//{
//    CreateGUIControls();
//}

SourceView::SourceView(wxWindow* parent, 
                       wxWindowID id /*= wxID_ANY*/,
                       const wxPoint& pos /*= wxDefaultPosition*/,
                       const wxSize& size /*= wxDefaultSize*/, 
                       long style /*= wxAUI_NB_DEFAULT_STYLE*/) :
wxAuiNotebook(parent, id, pos, size, style)
{
}

SourceView::~SourceView() {
}

//void SourceView::CreateGUIControls() {
//    std::list<Source> sources = m_mediator->GetSourceManager().GetList();
//    std::list<Source>::iterator it;
//
//    for (it = sources.begin(); it != sources.end(); ++it) {
//        CreatePage(*it);
//    }
//}

size_t SourceView::FindPageFromKey(const std::string &key) {
    for (size_t i = 0; i < GetPageCount(); ++i) {
        SourceViewPage *page = GetPage(i);

        if (page->GetKey() == key) {
            return i;
        }
    }

    return (size_t)wxNOT_FOUND;
}

SourceViewPage *SourceView::GetPage(size_t i) {
    wxWindow *page = wxAuiNotebook::GetPage(i);
    return dynamic_cast<SourceViewPage *>(page);
}

SourceViewPage *SourceView::GetSelected() {
    size_t sel = GetSelection();

    if (sel == wxNOT_FOUND) {
        return NULL;
    }

    return GetPage(sel);
}

void SourceView::CreatePage(const Source &source) {
    SourceViewPage *page = new SourceViewPage(m_mediator, this);
    page->Initialize(source);
    AddPage(page, page->GetTitle(), true);
}

void SourceView::ToggleBreakpoint() {
    SourceViewPage *page = GetSelected();

    if (page != NULL) {
        page->ToggleBreakpoint();
    }
}

struct RequestSourceHandler
{
    SourceView *m_view;
    wxDebugEvent m_event;

    explicit RequestSourceHandler(SourceView *view, wxDebugEvent &event)
        : m_view(view), m_event(event)
    {
        //wxLogMessage("RequestSourceHandler Added to wait source response.");
    }

    int operator()(const LuaCommand &/*command*/, const Source &source)
    {
        //wxLogMessage("RequestSourceHandler response received.");
        if (source.GetKey().empty()){
            return -1;
        }

        m_view->CreatePage(source);
        m_view->ProcessWindowEvent(m_event);
        return 0;
    }
};

void SourceView::OnUpdateSource(wxDebugEvent &event)
{
    //wxLogMessage("SourceView::OnUpdateSource");

    bool found = false;

    if (event.IsRefreshOnly()) {
        return;
    }

    for (size_t i = 0; i < GetPageCount(); ++i) {
        SourceViewPage *page = GetPage(i);

        if (page->GetKey() == event.GetKey()) {
            page->FocusCurrentLine(event.GetLine());

            // GetSelection is to avoid moving the focus carelessly.
            if (i != (size_t)GetSelection()) {
                SetSelection(i);
            }

            found = true;
        }
        else {
            page->FocusCurrentLine(-1);
        }
    }

    // If there is no appropriate source, request it.
    if (!found) {
        //wxLogMessage("SendRequestSource");
        m_mediator->GetEngine()->SendRequestSource(event.GetKey(),RequestSourceHandler(this, event));
    }
}

void SourceView::OnChangedState(wxDebugEvent &event) {
    SourceViewPage *page = GetSelected();
    if (page != NULL) {
        page->ChangeEnable(event.IsBreak());
    }
}

void SourceView::OnAddedSource(wxDebugEvent &event) {
    CreatePage(event.GetSource());
}

void SourceView::OnFocusErrorLine(wxDebugEvent &event) {
    for (size_t i = 0; i < GetPageCount(); ++i) {
        SourceViewPage *page = GetPage(i);

        if (page->GetKey() == event.GetKey()) {
            page->FocusErrorLine(event.GetLine());
            SetSelection(i);
            break;
        }
    }
}

void SourceView::OnFocusBacktraceLine(wxDebugEvent &event) {
    for (size_t i = 0; i < GetPageCount(); ++i) {
        SourceViewPage *page = GetPage(i);

        if (page->GetKey() == event.GetBacktrace().GetKey()) {
            page->FocusCurrentLine(event.GetLine(), false);
            SetSelection(i);
        }
        else {
            page->FocusCurrentLine(-1, false);
        }
    }
}

void SourceView::OnEndDebug(wxDebugEvent &/*event*/) {
    size_t count;
    while ((count = GetPageCount()) > 0) {
        DeletePage(count - 1);
    }
}

LUA_DEBUG_END
